package com.woniu.gateway.filter;

import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.common.ResponseData;
import com.woniu.common.ResponseEnum;
import com.woniu.common.dto.WhiteDTO;
import com.woniu.gateway.feign.WhiteFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.List;
import java.util.Set;

@Slf4j
@Component
@Order(1)//值越小优先级越高
public class LoginFilter implements GlobalFilter {
    @Autowired
    private ReactiveStringRedisTemplate redisTemplate;

    @Autowired
    private WhiteFeign whiteFeign;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("token");
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().toString();
        if (path.contains("/user/getCode")){
            return chain.filter(exchange);
        }

        if (checkWhite(path)){
            return chain.filter(exchange);
        }

        if (token == null) {
            return getVoidMono(exchange);
        }

        return redisTemplate.hasKey(token).flatMap(b -> {
            if (b) {
                String s = stringRedisTemplate.opsForValue().get(token);
                try {
                    boolean verify = JWTUtil.verify(s, "woniu".getBytes());
                    if (!verify) {
                        return getVoidMono(exchange);
                    }
                } catch (Exception e) {
                    log.error("login filter is error:{},token:{}", e, token);
                    return getVoidMono(exchange);
                }
                return chain.filter(exchange);
            }
            return getVoidMono(exchange);
        });
    }

    private static Mono<Void> getVoidMono(ServerWebExchange exchange) {
        log.error("login is error");
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = new byte[0];
        try {
            bytes = objectMapper.writeValueAsBytes(new ResponseData<>().fail(ResponseEnum.NO_LOGIN));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        response.setStatusCode(HttpStatus.FORBIDDEN);
        return response.writeWith(Mono.just(buffer));
    }

    private boolean checkWhite(String path) {
        Set<Object> whiteList = stringRedisTemplate.opsForHash().keys("WhiteList");
        for (Object white : whiteList) {
            if (path.equals(white)) {
                return true;
            }
        }
        return false;
    }

}
